#include "gxParam.h"
using namespace gx;
using namespace gx::base;

CGxParam::CGxParam(void):m_uCount(0)
{
}

CGxParam::~CGxParam(void)
{
    Clear();
}

bool CGxParam::SetBool(const String& strKey, bool val)
{
    return SetParamT(strKey, GX_DATA_TYPE_BOOL, val);
}

bool CGxParam::SetU8(const String& strKey, u8 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_U8, val);
}

bool CGxParam::SetS8(const String& strKey, s8 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_S8, val);
}

bool CGxParam::SetC8(const String& strKey, c8 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_C8, val);
}

bool CGxParam::SetU16(const String& strKey, u16 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_U16, val);
}

bool CGxParam::SetS16(const String& strKey, s16 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_S16, val);
}

bool CGxParam::SetU32(const String& strKey, u32 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_U32, val);
}

bool CGxParam::SetS32(const String& strKey, s32 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_S32, val);
}

bool CGxParam::SetU64(const String& strKey, u64 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_U64, val);
}

bool CGxParam::SetS64(const String& strKey, s64 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_S64, val);
}

bool CGxParam::SetF32(const String& strKey, f32 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_F32, val);
}

bool CGxParam::SetF64(const String& strKey, f64 val)
{
    return SetParamT(strKey, GX_DATA_TYPE_F64, val);
}

bool CGxParam::SetStr(const String& strKey, const String& val)
{
    return SetParamT(strKey, GX_DATA_TYPE_STRING, val);
}

bool CGxParam::SetPVoid(const String& strKey, void* val)
{
    return SetParamT(strKey, GX_DATA_TYPE_PVOID, val);
}

bool CGxParam::SetParam(const String& strKey, CGxPtr<IGxParam> gxpParam)
{
    if (Insert(strKey, GX_DATA_TYPE_PARAM, (void*)(IGxParam*)gxpParam))
    {
        gxpParam->AddRef();
        return true;
    }

    return false;
}

bool CGxParam::GetBool(const String& strKey, bool& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_BOOL, val);
}

bool CGxParam::GetU8(const String& strKey, u8& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_U8, val);
}

bool CGxParam::GetS8(const String& strKey, s8& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_S8, val);
}

bool CGxParam::GetC8(const String& strKey, c8& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_C8, val);
}

bool CGxParam::GetU16(const String& strKey, u16& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_U16, val);
}

bool CGxParam::GetS16(const String& strKey, s16& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_S16, val);
}

bool CGxParam::GetU32(const String& strKey, u32& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_U32, val);
}

bool CGxParam::GetS32(const String& strKey, s32& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_S32, val);
}

bool CGxParam::GetU64(const String& strKey, u64& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_U64, val);
}

bool CGxParam::GetS64(const String& strKey, s64& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_S64, val);
}

bool CGxParam::GetF32(const String& strKey, f32& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_F32, val);
}

bool CGxParam::GetF64(const String& strKey, f64& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_F64, val);
}

bool CGxParam::GetStr(const String& strKey, String& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_STRING, val);
}

bool CGxParam::GetPVoid(const String& strKey, void*& val)
{
    return GetParamT(strKey, GX_DATA_TYPE_PVOID, val);
}

bool CGxParam::GetParam(const String& strKey, CGxPtr<IGxParam>& gxpParam)
{
    void* pVoid = NULL;
    if (!Obtain(strKey, GX_DATA_TYPE_PARAM, pVoid))
    {
        return false;
    }

    gxpParam = (IGxParam*)pVoid;

    return true;
}

bool CGxParam::Remove(const String& strKey)
{
    u32 uHash = GetStrHash(strKey);
    MapParam::iterator it = m_mapParam.find(uHash);
    if (it == m_mapParam.end())
    {
        return false;
    }

    DelMapElem(it);
    m_mapParam.erase(it);
    return true;
}

bool CGxParam::Clear()
{
    //clear param ref and delete
    MapParam::iterator it = m_mapParam.begin();
    for (; it != m_mapParam.end(); ++it)
    {
        DelMapElem(it);
    }

    m_mapParam.clear();
    return true;
}

bool CGxParam::GetBuffer(c8*& pBuf, u32& uLen)
{
    return true;
}

bool CGxParam::SetBuffer(c8* pBuf, u32 uLen)
{
    return true;
}

bool CGxParam::GetNetBuffer(c8*& pBuf, u32& uLen)
{
    return true;
}

bool CGxParam::SetNetBuffer(c8* pBuf, u32 uLen)
{
    return true;
}

u32 CGxParam::GetStrHash( const String& strSrc )
{
    const s8* p = strSrc.c_str();
    u32 uLen = (u32)strSrc.length();
    u32 uHash = 0;
    for (u32 i = 0; i < uLen; i++)
    {
        uHash = (uHash >> 13) | (uHash << 19);
        uHash += *p;
    }
    return uHash;
}

bool CGxParam::Insert( const String& strKey, u8 cType, void* pVoid )
{
    u32 uHash = GetStrHash(strKey);
    if (m_mapParam.find(uHash) != m_mapParam.end())
    {
        return false;
    }

    ParamItem paramItem = {0};
    paramItem.cType = cType;
    paramItem.pVoid = pVoid;
    m_mapParam.insert(PairParam(uHash, paramItem));
    return true;
}

bool CGxParam::Obtain( const String& strKey, u8 cType, void*& pVoid )
{
    u32 uHash = GetStrHash(strKey);
    MapParam::iterator it = m_mapParam.find(uHash);
    if ( it == m_mapParam.end())
    {
        return false;
    }

    ParamItem paramItem = it->second;
    if (cType != paramItem.cType)
    {
        return false;
    }
    pVoid = paramItem.pVoid;

    return true;
}

void CGxParam::DelMapElem( MapParam::iterator it )
{
    ParamItem paramItem = it->second;
    if (paramItem.pVoid)
    {
        if (paramItem.cType == GX_DATA_TYPE_PARAM || paramItem.cType == GX_DATA_TYPE_GXPTR)
        {
            ((IGxRef*)paramItem.pVoid)->Release();
        }
        else
        {
            delete paramItem.pVoid;
        }
    }
}
